import RoactCss from "./RoactCss"

const UITextSizeConstraintPropertNames: Array<keyof Partial<WritableInstanceProperties<UITextSizeConstraint>>>
    = [
        'MaxTextSize',
        'MinTextSize',
    ]
const UIStrokePropertNames: Array<keyof Partial<WritableInstanceProperties<UIStroke>>>
    = [
        'Color',
        'Enabled',
        'LineJoinMode',
        'Thickness',
        'Transparency',
    ]
const GuiObjectPropertNames: Array<keyof Partial<WritableInstanceProperties<GuiObject>>>
    = ['Active', 'AnchorPoint', 'Archivable', 'AutoLocalize', 'AutomaticSize'
        , 'BackgroundColor', 'BackgroundColor3', 'BackgroundTransparency', 'BorderColor', 'BorderColor3',
        'BorderMode', 'BorderSizePixel', 'ClipsDescendants', 'Draggable', 'LayoutOrder',
        'Localize', 'Position', 'Rotation', 'Size', 'SizeConstraint', 'Transparency', 'Visible', 'ZIndex'
    ]
const GuiButtonPropertNames: Array<keyof Partial<WritableInstanceProperties<GuiButton>>>
    = [...GuiObjectPropertNames,
        'AutoButtonColor',
        'Modal',
        'Selected',
        'Style',
    ]
const framePropertNames: Array<keyof Partial<WritableInstanceProperties<Frame>>>
    = [...GuiObjectPropertNames]
const UIGridSytleLayoutPropertNames: Array<keyof Partial<WritableInstanceProperties<UIGridStyleLayout>>>
    = [
        'FillDirection',
        'HorizontalAlignment',
        'SortOrder',
        'VerticalAlignment']
const UIListLayoutPropertNames: Array<keyof Partial<WritableInstanceProperties<UIListLayout>>>
    = [...UIGridSytleLayoutPropertNames,
        'Padding'
    ]
const TextButtonPropertNames
    = [...GuiButtonPropertNames,
        'Font',
        'FontFace',
        'FontSize',
        'LineHeight',
        'MaxVisibleGraphemes',
        'RichText',
        'Text',
        'TextColor',
        'TextColor3',
        'TextScaled',
        'TextSize',
        'TextStrokeColor3',
        'TextStrokeTransparency',
        'TextTransparency',
        'TextTruncate',
        'TextWrap',
        'TextWrapped',
        'TextXAlignment',
        'TextYAlignment',
    ] as Array<keyof Partial<WritableInstanceProperties<TextButton>>>
const UIGridLayoutPropertNames: Array<keyof Partial<WritableInstanceProperties<UIGridLayout>>>
    = [...UIGridSytleLayoutPropertNames,
        'CellPadding',
        'CellSize',
        'FillDirectionMaxCells',
        'StartCorner',
    ]
const ScrollingFramePropertNames: Array<keyof Partial<WritableInstanceProperties<ScrollingFrame>>>
    = [...GuiObjectPropertNames, 'AutomaticCanvasSize', 'BottomImage', 'CanvasPosition', 'CanvasSize',
        'ElasticBehavior', 'HorizontalScrollBarInset', 'MidImage', 'ScrollBarImageColor3', 'ScrollBarImageTransparency',
        'ScrollBarThickness', 'ScrollingDirection', 'ScrollingEnabled',
        'TopImage',
        'VerticalScrollBarInset',
        'VerticalScrollBarPosition']
const UICornerPropertNames: Array<keyof Partial<WritableInstanceProperties<UICorner>>>
    = ['Archivable', 'CornerRadius']
const UIGradientPropertNames: Array<keyof Partial<WritableInstanceProperties<UIGradient>>>
    = ['Archivable', 'Color', 'Enabled', 'Offset', 'Rotation', 'Transparency']
const UIPaddingPropertNames: Array<keyof Partial<WritableInstanceProperties<UIPadding>>>
    = ['PaddingBottom',
        'PaddingLeft',
        'PaddingRight',
        'PaddingTop']
const ImageLabelPropertNames: Array<keyof Partial<WritableInstanceProperties<ImageLabel>>>
    = [...GuiObjectPropertNames, 'Image', 'ImageColor3', 'ImageRectOffset', 'ImageRectSize',
        'ImageTransparency', 'ResampleMode', 'ScaleType', 'SliceCenter', 'SliceScale', 'TileSize']


const ImageButtonPropertNames: Array<keyof Partial<WritableInstanceProperties<ImageButton>>>
    = [...GuiButtonPropertNames,
        'Image',
        'ImageColor3',
        'ImageRectOffset',
        'ImageRectSize',
        'ImageTransparency',
        'PressedImage',
        'ResampleMode',
        'ScaleType',
        'SliceCenter',
        'SliceScale',
        'TileSize',
        'HoverImage',
    ]
const UISizeConstraintPropertNames: Array<keyof Partial<WritableInstanceProperties<UISizeConstraint>>>
    = ['MaxSize', 'MinSize']
const TextLabelPropertNames
    = [...GuiObjectPropertNames, 'FontFace', 'Font', 'FontSize', 'LineHeight', 'MaxVisibleGraphemes', 'RichText', 'Text',
        'TextColor', 'TextColor3', 'TextScaled', 'TextSize', 'TextStrokeColor3', 'TextStrokeTransparency',
        'TextTransparency', 'TextTruncate', 'TextWrap', 'TextWrapped', 'TextXAlignment', 'TextYAlignment',] as Array<keyof Partial<WritableInstanceProperties<TextLabel>>>

const TextBoxPropertNames
    = [...GuiObjectPropertNames,
        'ClearTextOnFocus',
        'CursorPosition',
        'Font',
        'FontFace',
        'FontSize',
        'LineHeight',
        'MaxVisibleGraphemes',
        'MultiLine',
        'PlaceholderColor3',
        'PlaceholderText',
        'RichText',
        'SelectionStart',
        'ShowNativeInput',
        'Text',
        'TextColor',
        'TextColor3',
        'TextEditable',
        'TextScaled',
        'TextSize',
        'TextStrokeColor3',
        'TextStrokeTransparency',
        'TextTransparency',
        'TextTruncate',
        'TextWrap',
        'TextWrapped',
        'TextXAlignment',
        'TextYAlignment',] as Array<keyof Partial<WritableInstanceProperties<TextBox>>>
const ViewportFramePropertNames
    = [...GuiObjectPropertNames,
        'Ambient',
        'CurrentCamera',
        'ImageColor3',
        'ImageTransparency',
        'LightColor',
        'LightDirection',
    ] as Array<keyof Partial<WritableInstanceProperties<ViewportFrame>>>

// export const cssPrefab = game.GetService('StarterGui').FindFirstChild('css') as Instance

RoactCss.init()
function cssPre<T extends Instance>(css: Partial<WritableInstanceProperties<T>>,
    target: Partial<WritableInstanceProperties<T>>,
    propertyNames: Array<keyof Partial<WritableInstanceProperties<T>>>) {
    propertyNames.forEach(properName => {
        css[properName] = target[properName]
        // const value = target[properName]
        // if (typeIs(value, 'Color3')) {

        //     (css[properName] as any) = Color3.fromHex(value.ToHex())
        //     if (properName === 'BackgroundColor3') {
        //         print('Color3', value.ToHex())
        //         print((css[properName] as unknown as Color3).ToHex())
        //     }
        // } else {
        //     css[properName] = value
        // }
    });
}

export function cssFrame(target: any) {
    const css: Partial<WritableInstanceProperties<Frame>> = {}
    cssPre(css, target as Frame, framePropertNames)
    return css

}
export function cssScroll(target: any) {
    const css: Partial<WritableInstanceProperties<ScrollingFrame>> = {}
    cssPre(css, target as ScrollingFrame, ScrollingFramePropertNames)
    return css

}
export function cssUICorner(target: any) {
    const css: Partial<WritableInstanceProperties<UICorner>> = {}
    cssPre(css, target as UICorner, UICornerPropertNames)
    return css

}
export function cssUIGradient(target: any) {
    const css: Partial<WritableInstanceProperties<UIGradient>> = {}
    cssPre(css, target as UIGradient, UIGradientPropertNames)
    return css

}
export function cssUIGridLayout(target: any) {
    const css: Partial<WritableInstanceProperties<UIGridLayout>> = {}
    cssPre(css, target as UIGridLayout, UIGridLayoutPropertNames)
    return css

}
export function cssUIPading(target: any) {
    const css: Partial<WritableInstanceProperties<UIPadding>> = {}
    cssPre(css, target as UIPadding, UIPaddingPropertNames)
    return css

}
export function cssImageLabel(target: any) {
    const css: Partial<WritableInstanceProperties<ImageLabel>> = {}
    cssPre(css, target as ImageLabel, ImageLabelPropertNames)
    return css

}
export function cssUISizeConstraint(target: any) {
    const css: Partial<WritableInstanceProperties<UISizeConstraint>> = {}
    cssPre(css, target as UISizeConstraint, UISizeConstraintPropertNames)
    return css

}
export function cssTextLabel(target: any) {
    const css: Partial<WritableInstanceProperties<TextLabel>> = {}
    cssPre(css, target as TextLabel, TextLabelPropertNames)
    return css

}
export function cssTextButton(target: any) {
    const css: Partial<WritableInstanceProperties<TextButton>> = {}
    cssPre(css, target as TextLabel, TextButtonPropertNames)
    return css

}
export function cssTextBox(target: any) {
    const css: Partial<WritableInstanceProperties<TextBox>> = {}
    cssPre(css, target as TextBox, TextBoxPropertNames)
    return css

}
export function cssUIListLayout(target: any) {
    const css: Partial<WritableInstanceProperties<UIListLayout>> = {}
    cssPre(css, target as UIListLayout, UIListLayoutPropertNames)
    return css

}
export function cssUIStroke(target: any) {
    const css: Partial<WritableInstanceProperties<UIStroke>> = {}
    cssPre(css, target, UIStrokePropertNames)
    return css

}
export function css(target: Instance) {
    let properties
    switch (target.ClassName) {
        case 'Frame':
            properties = framePropertNames
            break;
        case 'ScrollingFrame':
            properties = ScrollingFramePropertNames
            break;
        case 'UICorner':
            properties = UICornerPropertNames
            break;
        case 'UIGradient':
            properties = UIGradientPropertNames
            break;
        case 'UIGridLayout':
            properties = UIGridLayoutPropertNames
            break;
        case 'UIPadding':
            properties = UIPaddingPropertNames
            break;
        //ImageLabel
        case 'ImageLabel':
            properties = ImageLabelPropertNames
            break;
        case 'ImageButton':
            properties = ImageButtonPropertNames
            break;
        case 'UISizeConstraint':
            properties = UISizeConstraintPropertNames
            break;
        case 'TextLabel':
            properties = TextLabelPropertNames
            break;
        case 'TextButton':
            properties = TextButtonPropertNames
            break;
        case 'TextBox':
            properties = TextBoxPropertNames
            break;
        case 'UIListLayout':
            properties = UIListLayoutPropertNames
            break;
        case 'UIStroke':
            properties = UIStrokePropertNames
            break;
        case 'UITextSizeConstraint':
            properties = UITextSizeConstraintPropertNames
            break;
        case 'ViewportFrame':
            properties = ViewportFramePropertNames
            break;

        default:
            throw ('not find class:' + target.ClassName)

    }
    const css = {}
    cssPre(css, target, properties as any)
    return css
}
function start(name: string, t: CSS) {
    let node = t.current
    const current = node.FindFirstChild(name)
    if (!current) {

        throw ('cont find ' + name)
    }
    t.current = current
    return t.current
}
export class CSS {

    constructor(screen = 'css', public current = game.GetService('StarterGui').FindFirstChild(screen) as Instance, path?: string[]) {
        if (path) {
            this.path(...path)
        }
    }
    css(name: string) {
        const r = css(this.start(name));
        (r as any).Name = name
        return r
    }
    cssEx(name: string) {
        const r = css(this.start(name));
        (r as any).Name = name;
        (r as any).css = {
            endCss: () => {
                this.end()
            }
        }
        return r
    }
    UIListLayout(name: string) {

        return cssUIListLayout(this.start(name))
    }
    TextLabel(name: string) {

        return cssTextLabel(this.start(name))
    }
    Frame(name: string) {

        const r = cssFrame(this.start(name))
        r.Name = name
        return r
    }
    ImageLabel(name: string) {

        return cssImageLabel(this.start(name))
    }
    ScrollingFrame(name: string) {

        return cssScroll(this.start(name))
    }
    UICorner(name: string) {
        return cssUICorner(this.start(name))
    }
    UIGradient(name: string) {
        return cssUIGradient(this.start(name))
    }
    UIPading(name: string) {
        return cssUIPading(this.start(name))
    }
    UISizeConstraint(name: string) {
        return cssUISizeConstraint(this.start(name))
    }
    UIGridLayout(name: string) {
        return cssUIGridLayout(this.start(name))
    }
    TextBox(name: string) {
        return cssTextBox(this.start(name))
    }
    TextButton(name: string) {
        return cssTextButton(this.start(name))
    }
    UIStroke(name: string) {
        return cssUIStroke(this.start(name))
    }
    path(...paths: string[]) {
        paths.forEach(path => {
            this.start(path)
        })
    }
    start(name: string, node = this.current) {
        // print('current', this.current)
        const current = node.WaitForChild(name)
        if (!current) {

            throw ('cont find ' + name)
        }
        this.current = current
        return this.current
    }
    end() {
        // print('current', this.current)
        const current = this.current.Parent
        if (!current) {

            throw ('cont find parent')
        }
        this.current = current
        return []
    }
}